home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
apps
/
gmemusage
/
gmemusage.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
14KB
|
634 lines
/*
* gmemusage.c
*
* Reveal system memory usage
*
* Copyright 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/sysmp.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <bstring.h>
#include <gl/gl.h>
#include <gl/device.h>
#include "process.h"
#include "draw.h"
#include "inode.h"
#include "print.h"
#define DEF_THRESH 500
#define DEF_DELTA 50
/*
* Set to 1 once the inode table has been initialized
*/
static int inodesInitted = 0;
/*
* static void
* PlaySound(char *sound)
*
* Description:
* run playaiff asynchronously to play a sound
*
* Parameters:
* sound
*/
static void
PlaySound(char *sound)
{
static int firstTime = 1;
static int ok = 0;
static pid_t pid;
int fd, stat;
if (firstTime) {
firstTime = 0;
if (sound) {
if (access("/usr/sbin/playaiff", F_OK | X_OK) == -1) {
perror("/usr/sbin/playiff");
return;
}
if (access(sound, F_OK) == -1) {
perror(sound);
return;
}
ok = 1;
}
}
if (!ok) {
return;
}
/*
* Don't interrupt it if the last one is still playing
*/
if (waitpid(pid, &stat, WNOHANG) == 0) {
return;
}
if (pid = fork()) {
return;
}
for (fd = getdtablesize(); fd > 2; fd--) {
close(fd);
}
setuid(getuid()); /* avoid security problems */
execl("/usr/sbin/playaiff", "playaiff", sound, NULL);
exit(-1);
}
/*
* static void
* InitInodes(void)
*
* Description:
* Make sure inodes are initted. This gets called from two
* different places, and the flag inodesInitted is global.
*/
static void
InitInodes(void)
{
if (!inodesInitted) {
WaitMessage("Initializing inode lookup table...", NULL);
InodeInit();
inodesInitted = 1;
}
}
/*
* char *
* HandleMouse(PROGRAM *usage, long mousex, long mousey, int *procMode,
* int dragging)
*
* Description:
* Handle mouse events. We use the mouse to select bars to
* display detailed breakdowns, and to leave detailed mode. The
* passed in procMode gets cleared if we should leave detailed
* mode.
*
* Parameters:
* usage current all programs usage being displayed
* mousex mouse horiz position
* mousey mouse vert position
* procMode pointer to variable that says whether we're already
* in procMode
* dragging 1 if we're dragging
*
* Returns:
* pointer to name of program selected
*/
char *
HandleMouse(PROGRAM *usage, long mousex, long mousey, int *procMode,
int dragging)
{
static char *oldProcName;
char *procName;
long originx, originy;
getorigin(&originx, &originy);
mousex -= originx;
mousey -= originy;
procName = Select(usage, mousex, mousey, procMode, dragging);
if (!procName && *procMode) {
return oldProcName;
}
if (procName) {
if (!inodesInitted && strcmp(procName, IRIX) != 0) {
if (dragging) {
unqdevice(MOUSEX);
unqdevice(MOUSEY);
}
InitInodes();
if (dragging) {
qdevice(MOUSEX);
qdevice(MOUSEY);
}
}
*procMode = 1;
if (oldProcName) {
free(oldProcName);
}
oldProcName = procName;
}
return procName;
}
int
main(int argc, char *argv[])
{
int glfd, opt, threshDelta = DEF_DELTA, doHelp = 0, doFreeze = 0;
int gotInput, doProcMode = 0, needNewColors = 0, inodesInitted = 0;
int barTotal, progBarTotal, numBars, numProgBars, dragging = 0;
int oldProgBarTotal, soundThresh = 12, pgsize;
fd_set fds, tfds;
PROGRAM *usage = NULL, *lastUsage = NULL;
PROGRAM *progUsage = NULL, *lastProgUsage = NULL;
long physMem, freeMem, threshHold = DEF_THRESH;
long dev, originx, originy;
short value, mousex, mousey;
struct timeval tv;
char *str, *procName = NULL, *newProcName = NULL;
PROGNAME *progNames = NULL, *name, *prev = NULL;
UsageType type, newType;
SecondType stype, newStype;
long usecTimeOut = 500000, secTimeOut = 0, msecTimeOut;
struct rminfo rminfo;
char *usageSound = getenv("USAGESOUND");
if (geteuid() != 0) {
fprintf(stderr, "%s must be run as root or it must be setuid root.\n",
argv[0]);
exit(1);
}
type = newType = Physical;
stype = newStype = None;
/*
* Process command line arguments
*/
opterr = 0;
while ((opt = getopt(argc, argv, "a:g:i:d:mprst:u")) != EOF) {
switch (opt) {
case 'a':
usageSound = optarg;
break;
case 'g':
soundThresh = atoi(optarg);
break;
case 'i':
msecTimeOut = atoi(optarg);
secTimeOut = msecTimeOut / 1000;
usecTimeOut = 1000 * (msecTimeOut % 1000);
break;
case 'd':
threshDelta = atoi(optarg);
if (threshDelta <= 0) {
fprintf(stderr, "Resetting delta from %d\n", threshDelta);
threshDelta = DEF_DELTA;
}
break;
case 'm':
type = newType = MappedObjects;
break;
case 'p':
type = newType = Physical;
break;
case 'r':
type = newType = Resident;
break;
case 's':
type = newType = Size;
break;
case 't':
threshHold = atoi(optarg);
break;
case 'u':
InvalidateInodeTable();
break;
default:
doHelp = 1;
}
}
while (optind < argc) {
name = malloc(sizeof *name);
name->name = argv[optind];
name->next = NULL;
if (prev) {
prev->next = name;
} else {
progNames = name;
}
prev = name;
optind++;
}
if (sysmp(MP_SAGET, MPSA_RMINFO, &rminfo, sizeof rminfo) == -1) {
perror("sysmp");
return 1;
}
pgsize = getpagesize()/1024;
physMem = rminfo.physmem * pgsize;
foreground();
Init(progNames, threshHold);
glfd = qgetfd();
qdevice(ESCKEY);
qdevice(HKEY);
qdevice(MKEY);
qdevice(PKEY);
qdevice(RKEY);
qdevice(SKEY);
qdevice(TKEY);
qdevice(VKEY);
qdevice(UPARROWKEY);
qdevice(DOWNARROWKEY);
qdevice(SPACEKEY);
qdevice(WINFREEZE);
qdevice(WINTHAW);
qdevice(LEFTMOUSE);
tie(LEFTMOUSE, MOUSEX, MOUSEY);
FD_ZERO(&fds);
FD_SET(glfd, &fds);
tv.tv_sec = secTimeOut;
tv.tv_usec = usecTimeOut;
gotInput = 0;
if (type == MappedObjects) {
InitInodes();
}
while (1) {
/*
* Draw the window, either help or the usage chart
*/
if (!doFreeze) {
if (doHelp) {
Help();
} else {
/*
* If the user pressed a key that we can deal with without
* getting all our data again, just redraw.
*/
if (!gotInput || type != newType || stype != newStype) {
stype = newStype;
type = newType;
if (lastUsage) {
FreeUsage(lastUsage);
}
lastUsage = usage;
if (lastProgUsage) {
FreeUsage(lastProgUsage);
}
lastProgUsage = progUsage;
if (type == MappedObjects) {
GetObjInfo(doProcMode ? procName : NULL,
&usage, &progUsage);
} else {
GetProcInfo(doProcMode ? procName : NULL,
&usage, &progUsage);
}
if (sysmp(MP_SAGET, MPSA_RMINFO, &rminfo,
sizeof rminfo) == -1) {
perror("sysmp");
return 1;
}
freeMem = rminfo.freemem * pgsize;
if (usage) {
usage = DrawSetup(usage,
needNewColors ? NULL : lastUsage,
physMem, freeMem, type, stype, 1,
&barTotal, &numBars);
}
if (progUsage) {
progUsage = DrawSetup(progUsage,
needNewColors ?
NULL : lastProgUsage,
physMem, freeMem,
type, stype, 0, &progBarTotal,
&numProgBars);
if (usageSound) {
if (oldProgBarTotal == 0 ||
oldProgBarTotal > progBarTotal) {
oldProgBarTotal = progBarTotal;
} else if (progBarTotal >
oldProgBarTotal + soundThresh) {
PlaySound(usageSound);
oldProgBarTotal = progBarTotal;
}
}
}
if (doProcMode && !progUsage) {
doProcMode = 0;
}
needNewColors = 0;
}
if (doProcMode && progUsage) {
DrawShadow(usage, barTotal, procName);
Draw(progUsage, progBarTotal, numProgBars,
procName, type, stype);
} else if (usage) {
Draw(usage, barTotal, numBars, NULL, type, stype);
}
gotInput = 0;
}
}
/*
* Wait for GL events, timing out after half a second
*/
tfds = fds;
if (select(glfd + 1, &tfds, NULL, NULL,
(doHelp || doFreeze) ? NULL : &tv) < 0) {
perror("select");
return 1;
}
/*
* Process GL events
*/
if (FD_ISSET(glfd, &tfds)) {
while (qtest()) {
dev = qread(&value);
switch (dev) {
case HKEY:
/*
* Help
*/
if (value == 0) {
doHelp = 1;
needNewColors = 1;
}
break;
case SPACEKEY:
/*
* End of help
*/
if (value == 0) {
doProcMode = 0;
doHelp = 0;
}
break;
case MKEY:
if (value == 0) {
newStype = stype % Phys;
newType = MappedObjects;
doHelp = 0;
InitInodes();
needNewColors = 1;
}
break;
case PKEY:
/*
* Physical Memory Breakdown
*/
if (value == 0) {
if (procName && strcmp(procName, IRIX) == 0) {
newStype = None;
} else {
newStype = stype % Phys;
}
newType = Physical;
doHelp = 0;
needNewColors = 1;
}
break;
case RKEY:
/*
* Resident Sizes of Processes
*/
if (value == 0) {
if (!doProcMode
|| strcmp(procName, IRIX) != 0) {
newStype = stype % Res;
newType = Resident;
doHelp = 0;
needNewColors = 1;
}
}
break;
case SKEY:
/*
* Total Sizes of Processes
*/
if (value == 0) {
if (!doProcMode
|| strcmp(procName, IRIX) != 0) {
newStype = stype % (Res + 1);
newType = Size;
doHelp = 0;
needNewColors = 1;
}
}
break;
case TKEY:
if (value == 0) {
if (doProcMode && progUsage) {
PrintUsage(stdout, PRProc, progUsage, procName);
} else if (usage) {
PrintUsage(stdout,
type == MappedObjects ? PRMaps : PRAll,
usage, NULL);
}
}
break;
case VKEY:
if (value == 0) {
doHelp = 0;
newStype = stype + 1;
switch (type) {
case Size:
newStype %= Res + 1;
break;
case Resident:
newStype %= Res;
break;
case Physical:
if (procName && strcmp(procName, IRIX) == 0) {
newStype = None;
break;
}
/* intentional fall through */
case MappedObjects:
newStype %= Phys;
break;
default:
newStype = None;
break;
}
}
break;
case ESCKEY:
/*
* Exit
*/
if (value == 0) {
exit(0);
}
break;
case REDRAW:
/*
* Resize event
*/
gotInput = 1;
Resize();
break;
case UPARROWKEY:
/*
* Increase threshhold
*/
if (value == 0) {
if (threshHold == 1)
threshHold = 0;
threshHold += threshDelta;
SetThreshHold(threshHold);
doHelp = 0;
needNewColors = 1;
}
break;
case DOWNARROWKEY:
/*
* Decrease threshhold
*/
if (value == 0) {
if (threshHold == threshDelta)
threshHold = 1;
else
threshHold -= threshDelta;
if (threshHold < 0) {
threshHold = 0;
}
SetThreshHold(threshHold);
doHelp = 0;
needNewColors = 1;
}
break;
case MOUSEX:
needNewColors = 1;
mousex = value;
procName = HandleMouse(usage, mousex, mousey,
&doProcMode, 1);
oldProgBarTotal = 0;
break;
case MOUSEY:
needNewColors = 1;
mousey = value;
procName = HandleMouse(usage, mousex, mousey,
&doProcMode, 1);
oldProgBarTotal = 0;
break;
case LEFTMOUSE:
needNewColors = 1;
(void)qread(&mousex);
(void)qread(&mousey);
if (usage && !doHelp && value) {
/*
* This extra flag prevents switching bars if
* the user is moving the mouse at the same
* time that a bar is selected; if we start
* queueing mouse motion right away, we'll
* shift bars because off the vertical offset
* of the shadow chart.
*/
int prevDoProcMode = doProcMode;
procName = HandleMouse(usage, mousex, mousey,
&doProcMode, dragging);
oldProgBarTotal = 0;
if (procName && strcmp(procName, IRIX) == 0) {
newStype = None;
}
if (prevDoProcMode && !dragging) {
qdevice(MOUSEX);
qdevice(MOUSEY);
dragging = 1;
}
}
if (!value && dragging) {
unqdevice(MOUSEX);
unqdevice(MOUSEY);
dragging = 0;
}
break;
case WINFREEZE:
doFreeze = 1;
break;
case WINTHAW:
doFreeze = 0;
break;
default:
break;
}
}
}
}
return 0;
}